package com.kexio.log.analytics.adapter;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import com.kexio.log.analytics.service.PerformanceAnalyzer;

/**
 * PerformanceMonitorAspect 适配器
 * 
 * 与现有的 PerformanceMonitorAspect 集成，提供非侵入式的性能分析功能
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@Component
@ConditionalOnClass(name = "com.kexio.auth.aop.PerformanceMonitorAspect")
@ConditionalOnProperty(prefix = "kexio.log.analytics", name = "enabled", havingValue = "true")
public class PerformanceMonitorAdapter {
    
    private static final Logger logger = LoggerFactory.getLogger(PerformanceMonitorAdapter.class);
    
    @Autowired(required = false)
    private PerformanceAnalyzer performanceAnalyzer;
    
    // 性能阈值 (毫秒)
    private static final long SLOW_THRESHOLD = 1000;
    private static final long WARNING_THRESHOLD = 3000;
    
    // 性能统计
    private final AtomicLong totalMethods = new AtomicLong(0);
    private final AtomicLong slowMethods = new AtomicLong(0);
    private final AtomicLong errorMethods = new AtomicLong(0);
    
    // 按方法统计
    private final Map<String, PerformanceMetrics> methodMetrics = new ConcurrentHashMap<>();
    
    /**
     * 初始化适配器
     */
    public void initialize() {
        try {
            logger.info("初始化 PerformanceMonitorAspect 适配器");
            
            if (performanceAnalyzer != null) {
                logger.info("性能分析器已启用");
            }
            
        } catch (Exception e) {
            logger.warn("PerformanceMonitorAspect 适配器初始化失败: {}", e.getMessage());
        }
    }
    
    /**
     * 记录方法性能指标
     * 
     * @param className 类名
     * @param methodName 方法名
     * @param layer 层级 (CONTROLLER, SERVICE, MAPPER)
     * @param executionTime 执行时间 (毫秒)
     * @param isSuccess 是否成功
     * @param exception 异常信息 (如果有)
     * @param memoryUsage 内存使用量 (字节)
     */
    public void recordMethodPerformance(String className, String methodName, String layer,
                                       long executionTime, boolean isSuccess, Throwable exception,
                                       long memoryUsage) {
        try {
            totalMethods.incrementAndGet();
            
            String methodKey = className + "." + methodName;
            
            // 更新方法指标
            PerformanceMetrics metrics = methodMetrics.computeIfAbsent(methodKey, 
                k -> new PerformanceMetrics(methodKey));
            metrics.addExecution(executionTime, isSuccess, memoryUsage);
            
            // 统计慢方法
            if (executionTime > SLOW_THRESHOLD) {
                slowMethods.incrementAndGet();
            }
            
            // 统计错误
            if (!isSuccess) {
                errorMethods.incrementAndGet();
            }
            
            // 委托给性能分析器
            if (performanceAnalyzer != null) {
                performanceAnalyzer.analyzeMethodPerformance(
                    className, methodName, layer, executionTime, isSuccess, exception, memoryUsage
                );
            }
            
            // 记录警告
            if (executionTime > WARNING_THRESHOLD) {
                logger.warn("方法执行严重超时: {}.{} [{}] - {}ms", 
                           className, methodName, layer, executionTime);
            } else if (executionTime > SLOW_THRESHOLD) {
                logger.debug("方法执行较慢: {}.{} [{}] - {}ms", 
                            className, methodName, layer, executionTime);
            }
            
        } catch (Exception e) {
            logger.error("记录方法性能指标失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 记录系统资源使用情况
     * 
     * @param cpuUsage CPU 使用率 (0-100)
     * @param memoryUsage 内存使用量 (字节)
     * @param freeMemory 可用内存 (字节)
     * @param activeThreads 活跃线程数
     */
    public void recordSystemMetrics(double cpuUsage, long memoryUsage, long freeMemory, int activeThreads) {
        try {
            // 委托给性能分析器
            if (performanceAnalyzer != null) {
                performanceAnalyzer.analyzeSystemMetrics(cpuUsage, memoryUsage, freeMemory, activeThreads);
            }
            
            // 资源使用预警
            if (cpuUsage > 80) {
                logger.warn("CPU 使用率过高: {}%", cpuUsage);
            }
            
            double memoryUsagePercent = (double) memoryUsage / (memoryUsage + freeMemory) * 100;
            if (memoryUsagePercent > 85) {
                logger.warn("内存使用率过高: {:.2f}%", memoryUsagePercent);
            }
            
        } catch (Exception e) {
            logger.error("记录系统指标失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 分析请求链路性能
     * 
     * @param traceId 链路追踪 ID
     * @param spans 调用链节点
     */
    public void analyzeRequestTrace(String traceId, List<TraceSpan> spans) {
        try {
            // 委托给性能分析器
            if (performanceAnalyzer != null) {
                performanceAnalyzer.analyzeRequestTrace(traceId, spans);
            }
            
            // 分析链路总耗时
            long totalTime = spans.stream().mapToLong(TraceSpan::getDuration).sum();
            if (totalTime > 5000) { // 超过 5 秒的请求链路
                logger.warn("请求链路耗时过长: traceId={}, totalTime={}ms, spans={}", 
                           traceId, totalTime, spans.size());
            }
            
        } catch (Exception e) {
            logger.error("分析请求链路失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 获取性能统计信息
     * 
     * @return 性能统计数据
     */
    public PerformanceStatistics getStatistics() {
        try {
            long total = totalMethods.get();
            long slow = slowMethods.get();
            long errors = errorMethods.get();
            
            double slowRate = total > 0 ? (double) slow / total : 0.0;
            double errorRate = total > 0 ? (double) errors / total : 0.0;
            
            // 获取最慢的方法 (Top 10)
            List<PerformanceMetrics> slowestMethods = methodMetrics.values().stream()
                .sorted((a, b) -> Double.compare(b.getAverageTime(), a.getAverageTime()))
                .limit(10)
                .collect(Collectors.toList());
            
            return new PerformanceStatistics(
                total, slow, errors, slowRate, errorRate,
                slowestMethods, LocalDateTime.now()
            );
            
        } catch (Exception e) {
            logger.error("获取性能统计失败: {}", e.getMessage(), e);
            return new PerformanceStatistics();
        }
    }
    
    /**
     * 重置统计数据
     */
    public void resetStatistics() {
        totalMethods.set(0);
        slowMethods.set(0);
        errorMethods.set(0);
        methodMetrics.clear();
        
        logger.info("性能统计数据已重置");
    }
    
    /**
     * 检查适配器是否可用
     * 
     * @return 是否可用
     */
    public boolean isAvailable() {
        return performanceAnalyzer != null;
    }
    
    /**
     * 方法性能指标
     */
    public static class PerformanceMetrics {
        private String methodName;
        private AtomicLong totalCalls = new AtomicLong(0);
        private AtomicLong totalTime = new AtomicLong(0);
        private AtomicLong errors = new AtomicLong(0);
        private AtomicLong maxTime = new AtomicLong(0);
        private AtomicLong minTime = new AtomicLong(Long.MAX_VALUE);
        private AtomicLong totalMemory = new AtomicLong(0);
        
        public PerformanceMetrics(String methodName) {
            this.methodName = methodName;
        }
        
        public void addExecution(long executionTime, boolean isSuccess, long memoryUsage) {
            totalCalls.incrementAndGet();
            totalTime.addAndGet(executionTime);
            totalMemory.addAndGet(memoryUsage);
            
            if (!isSuccess) {
                errors.incrementAndGet();
            }
            
            // 更新最大/最小时间
            maxTime.updateAndGet(val -> Math.max(val, executionTime));
            minTime.updateAndGet(val -> Math.min(val, executionTime));
        }
        
        public double getAverageTime() {
            long calls = totalCalls.get();
            return calls > 0 ? (double) totalTime.get() / calls : 0.0;
        }
        
        public double getAverageMemory() {
            long calls = totalCalls.get();
            return calls > 0 ? (double) totalMemory.get() / calls : 0.0;
        }
        
        // Getters
        public String getMethodName() { return methodName; }
        public long getTotalCalls() { return totalCalls.get(); }
        public long getTotalTime() { return totalTime.get(); }
        public long getErrors() { return errors.get(); }
        public long getMaxTime() { return maxTime.get(); }
        public long getMinTime() { return minTime.get() == Long.MAX_VALUE ? 0 : minTime.get(); }
        public long getTotalMemory() { return totalMemory.get(); }
    }
    
    /**
     * 链路追踪节点
     */
    public static class TraceSpan {
        private String spanId;
        private String operationName;
        private long startTime;
        private long duration;
        
        public TraceSpan(String spanId, String operationName, long startTime, long duration) {
            this.spanId = spanId;
            this.operationName = operationName;
            this.startTime = startTime;
            this.duration = duration;
        }
        
        // Getters and Setters
        public String getSpanId() { return spanId; }
        public void setSpanId(String spanId) { this.spanId = spanId; }
        
        public String getOperationName() { return operationName; }
        public void setOperationName(String operationName) { this.operationName = operationName; }
        
        public long getStartTime() { return startTime; }
        public void setStartTime(long startTime) { this.startTime = startTime; }
        
        public long getDuration() { return duration; }
        public void setDuration(long duration) { this.duration = duration; }
    }
    
    /**
     * 性能统计信息
     */
    public static class PerformanceStatistics {
        private long totalMethods;
        private long slowMethods;
        private long errorMethods;
        private double slowRate;
        private double errorRate;
        private List<PerformanceMetrics> slowestMethods;
        private LocalDateTime timestamp;
        
        public PerformanceStatistics() {
            this.timestamp = LocalDateTime.now();
        }
        
        public PerformanceStatistics(long totalMethods, long slowMethods, long errorMethods,
                                   double slowRate, double errorRate, List<PerformanceMetrics> slowestMethods,
                                   LocalDateTime timestamp) {
            this.totalMethods = totalMethods;
            this.slowMethods = slowMethods;
            this.errorMethods = errorMethods;
            this.slowRate = slowRate;
            this.errorRate = errorRate;
            this.slowestMethods = slowestMethods;
            this.timestamp = timestamp;
        }
        
        // Getters and Setters
        public long getTotalMethods() { return totalMethods; }
        public void setTotalMethods(long totalMethods) { this.totalMethods = totalMethods; }
        
        public long getSlowMethods() { return slowMethods; }
        public void setSlowMethods(long slowMethods) { this.slowMethods = slowMethods; }
        
        public long getErrorMethods() { return errorMethods; }
        public void setErrorMethods(long errorMethods) { this.errorMethods = errorMethods; }
        
        public double getSlowRate() { return slowRate; }
        public void setSlowRate(double slowRate) { this.slowRate = slowRate; }
        
        public double getErrorRate() { return errorRate; }
        public void setErrorRate(double errorRate) { this.errorRate = errorRate; }
        
        public List<PerformanceMetrics> getSlowestMethods() { return slowestMethods; }
        public void setSlowestMethods(List<PerformanceMetrics> slowestMethods) { this.slowestMethods = slowestMethods; }
        
        public LocalDateTime getTimestamp() { return timestamp; }
        public void setTimestamp(LocalDateTime timestamp) { this.timestamp = timestamp; }
    }
}
